/**
 * Copyright 2009 Emory University
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated  documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions: The 
 * above copyright notice and this permission notice shall be included in all 
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
package com.markgrand.structuredSql;

/**
 * Append a Select statement to a StringBuilder.
 * 
 * @author Mark Grand
 */
class Select protected ( // val distinctList:DistinctList,
                         val selectList:SelectList,
                         val fromList:FromList,
                         val whereConstraint:Option[WhereConstraint],
                         // val groupByConstraint:GroupByConstraint,
                         // val havingConstraint:HavingConstraint,
                         // val setOperation:SetOperation, // UNION, INTERSECT, EXCEPT
                         val orderByConstraint:Option[OrderByConstraint],
                         // val  limitConstraint:LimitConstraint
                         // val offsetConstraint:OffsetConstraint
                         val selectFor:Option[SelectForClause]
                        ) extends SQLStatement with SQLInsertValueAppender {
  if (selectList==null) {
    throw new NullPointerException("Select list must not be null")
  }
  if (fromList==null) {
    throw new NullPointerException("From list must not be null")
  }

  def append(builder:StringBuilder) {
    builder.append("SELECT ")
    selectList.append(builder)
    builder.append(" ")
    fromList.append(builder)
    if (whereConstraint.isDefined) {
      builder.append(" ")
      whereConstraint.get.append(builder)
    }
    if (orderByConstraint.isDefined) {
      builder.append(" ")
      orderByConstraint.get.append(builder)
    }
    if (selectFor.isDefined) {
      builder.append(" ")
      selectFor.get.append(builder)
    }
  }
}

object Select {
  def apply(selectList:SelectList, fromList:FromList) = {
    new Select(selectList, fromList, None, None, None)
  }
  def apply(selectList:SelectList, fromList:FromList, selectFor:SelectForClause) = {
    new Select(selectList, fromList, None, None, Some(selectFor))
  }
  def apply(selectList:SelectList, fromList:FromList, whereConstraint:WhereConstraint) = {
    new Select(selectList, fromList, Some(whereConstraint), None, None)
  }
  def apply(selectList:SelectList, fromList:FromList, whereConstraint:WhereConstraint, selectFor:SelectForClause) = {
    new Select(selectList, fromList, Some(whereConstraint), None, Some(selectFor))
  }
  def apply(selectList:SelectList, fromList:FromList, orderByConstraint:OrderByConstraint) = {
    new Select(selectList, fromList, None, Some(orderByConstraint), None)
  }
  def apply(selectList:SelectList, fromList:FromList, orderByConstraint:OrderByConstraint, selectFor:SelectForClause) = {
    new Select(selectList, fromList, None, Some(orderByConstraint), Some(selectFor))
  }
  def apply(selectList:SelectList, fromList:FromList, whereConstraint:WhereConstraint, orderByConstraint:OrderByConstraint) = {
    new Select(selectList, fromList, Some(whereConstraint), Some(orderByConstraint), None)
  }
  def apply(selectList:SelectList, fromList:FromList, whereConstraint:WhereConstraint, orderByConstraint:OrderByConstraint, selectFor:SelectForClause) = {
    new Select(selectList, fromList, Some(whereConstraint), Some(orderByConstraint), Some(selectFor))
  }
  def apply(selectList:SelectList, fromList:FromList, whereConstraint:Option[WhereConstraint],
            orderByConstraint:Option[OrderByConstraint], selectFor:Option[SelectForClause]) ={
    new Select(selectList, fromList, whereConstraint, orderByConstraint, selectFor)
  }
}
